package com.hui.qiniucloud.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hui.qiniucloud.config.DoubaoProperties;
import com.hui.qiniucloud.dto.ImageGenerateRequest;
import com.hui.qiniucloud.dto.ImageGenerateResponse;
import com.hui.qiniucloud.entity.AICharacter;
import com.hui.qiniucloud.service.IDoubaoUniversalService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class DoubaoUniversalService implements IDoubaoUniversalService {

    private final WebClient webClient;
    private final ObjectMapper objectMapper;
    private final DoubaoProperties doubaoProperties;

    @Autowired
    public DoubaoUniversalService(DoubaoProperties doubaoProperties) {
        this.doubaoProperties = doubaoProperties;
        this.webClient = WebClient.builder()
                .baseUrl(doubaoProperties.getApi().getEndpoint())
                .build();
        this.objectMapper = new ObjectMapper();
    }

    /**
     * 通用聊天接口 - 非流式响应
     * @param message 用户消息
     * @return AI回复内容
     */
    public Mono<String> chat(String message) {
        return chat(message, null, null);
    }

    /**
     * 带系统提示的聊天接口
     * @param message 用户消息
     * @param systemPrompt 系统提示词
     * @return AI回复内容
     */
    public Mono<String> chatWithSystem(String message, String systemPrompt) {
        return chat(message, systemPrompt, null);
    }

    /**
     * 带历史记录的聊天接口
     * @param message 用户消息
     * @param systemPrompt 系统提示词（可选）
     * @param chatHistory 聊天历史记录
     * @return AI回复内容
     */
    public Mono<String> chat(String message, String systemPrompt, List<Map<String, String>> chatHistory) {
        List<Map<String, String>> messages = new ArrayList<>();

        // 添加系统提示词
        if (systemPrompt != null && !systemPrompt.trim().isEmpty()) {
            messages.add(Map.of(
                "role", "system",
                "content", systemPrompt
            ));
        }

        // 添加历史对话
        if (chatHistory != null && !chatHistory.isEmpty()) {
            messages.addAll(chatHistory);
        }

        // 添加用户当前消息
        messages.add(Map.of(
            "role", "user",
            "content", message
        ));

        Map<String, Object> requestBody = Map.of(
            "model", "doubao-1-5-pro-32k-250115",  // 使用正确的模型名称
            "messages", messages,
            "thinking", Map.of("type", "disabled"),  // 关闭思考过程
            "stream", false,  // 非流式
            "temperature", 0.7,  // 与成功配置相同
            "max_tokens", 500   // 与成功配置相同
        );

        log.info("开始发送豆包API请求: URL={}, 模型={}, 消息数量={}",
                doubaoProperties.getApi().getEndpoint() + "/chat/completions",
                "doubao-1-5-pro-32k-250115",
                messages.size());
        log.info("请求消息内容: {}", messages);

        return webClient.post()
                .uri("/chat/completions")
                .header("Authorization", "Bearer 70def220-00d9-4bef-ae6d-2d822fed2a98")  // 使用与成功配置相同的API Key
                .header("Content-Type", "application/json")
                .bodyValue(requestBody)
                .retrieve()
                .onStatus(status -> !status.is2xxSuccessful(),
                    response -> {
                        log.error("豆包API返回非成功状态码: {}", response.statusCode());
                        return response.bodyToMono(String.class)
                            .doOnNext(errorBody -> log.error("错误响应体: {}", errorBody))
                            .map(errorBody -> {
                                return new RuntimeException("豆包API错误: " + response.statusCode() + " - " + errorBody);
                            });
                    })
                .bodyToMono(String.class)
                .doOnNext(responseBody -> log.info("豆包API原始响应: {}", responseBody))
                .timeout(Duration.ofSeconds(doubaoProperties.getApi().getTimeout()))
                .map(this::extractContentFromResponse)
                .doOnNext(response -> log.info("豆包API最终响应内容: {}", response))
                .doOnError(ex -> log.error("豆包API调用过程中发生错误: ", ex))
                .onErrorMap(ex -> {
                    log.error("豆包API调用失败，错误详情: {}", ex.getMessage(), ex);
                    return new RuntimeException("AI服务暂时不可用，请稍后重试: " + ex.getMessage());
                });
    }

    /**
     * 自定义模型和参数的聊天接口
     * @param message 用户消息
     * @param systemPrompt 系统提示词
     * @param chatHistory 聊天历史
     * @param model 模型名称
     * @param temperature 温度参数(0-1)
     * @param maxTokens 最大token数
     * @return AI回复内容
     */
    public Mono<String> chatWithCustomParams(String message, String systemPrompt,
                                           List<Map<String, String>> chatHistory,
                                           String model, Double temperature, Integer maxTokens) {
        List<Map<String, String>> messages = new ArrayList<>();

        if (systemPrompt != null && !systemPrompt.trim().isEmpty()) {
            messages.add(Map.of("role", "system", "content", systemPrompt));
        }

        if (chatHistory != null && !chatHistory.isEmpty()) {
            messages.addAll(chatHistory);
        }

        messages.add(Map.of("role", "user", "content", message));

        Map<String, Object> requestBody = Map.of(
            "model", model != null ? model : doubaoProperties.getApi().getModel(),
            "messages", messages,
            "thinking", Map.of("type", "disabled"),  // 关闭思考过程
            "stream", false,
            "temperature", temperature != null ? temperature : doubaoProperties.getDefaults().getTemperature(),
            "max_tokens", maxTokens != null ? maxTokens : doubaoProperties.getDefaults().getMaxTokens()
        );

        return webClient.post()
                .uri("/chat/completions")
                .header("Authorization", "Bearer " + doubaoProperties.getApi().getKey())
                .header("Content-Type", "application/json")
                .bodyValue(requestBody)
                .retrieve()
                .bodyToMono(String.class)
                .timeout(Duration.ofSeconds(doubaoProperties.getApi().getTimeout()))
                .map(this::extractContentFromResponse)
                .doOnNext(response -> log.info("豆包API响应: {}", response))
                .onErrorMap(ex -> {
                    log.error("豆包API调用失败", ex);
                    return new RuntimeException("AI服务暂时不可用，请稍后重试");
                });
    }

    /**
     * 从API响应中提取内容
     */
    private String extractContentFromResponse(String responseJson) {
        try {
            log.info("原始豆包API响应: {}", responseJson);
            JsonNode jsonNode = objectMapper.readTree(responseJson);

            // 检查是否有error
            if (jsonNode.has("error")) {
                String errorMessage = jsonNode.get("error").get("message").asText();
                log.error("豆包API返回错误: {}", errorMessage);
                throw new RuntimeException("AI服务错误: " + errorMessage);
            }

            // 提取回复内容 (非流式响应格式)
            if (jsonNode.has("choices") && jsonNode.get("choices").isArray()
                && jsonNode.get("choices").size() > 0) {
                JsonNode choice = jsonNode.get("choices").get(0);
                if (choice.has("message") && choice.get("message").has("content")) {
                    String content = choice.get("message").get("content").asText();
                    log.info("提取到内容: {}", content);
                    return content;
                }
            }

            log.warn("未找到有效的回复内容: {}", responseJson);
            return "抱歉，我暂时无法回复您的问题。";

        } catch (Exception e) {
            log.error("解析响应失败: {}", responseJson, e);
            throw new RuntimeException("响应解析失败: " + e.getMessage());
        }
    }

    /**
     * 从SSE流式数据中提取内容 (用于流式响应)
     */
    private String extractContentFromSseData(String data) {
        try {
            log.debug("解析SSE数据: {}", data);
            JsonNode jsonNode = objectMapper.readTree(data);

            if (jsonNode.has("choices") && jsonNode.get("choices").isArray() && jsonNode.get("choices").size() > 0) {
                JsonNode choice = jsonNode.get("choices").get(0);
                if (choice.has("delta") && choice.get("delta").has("content")) {
                    String content = choice.get("delta").get("content").asText();
                    log.debug("提取到SSE内容: [{}]", content);
                    return content;
                }
            }

            return "";
        } catch (Exception e) {
            log.error("解析SSE数据失败: {}", data, e);
            return "";
        }
    }

    /**
     * 角色扮演聊天接口
     * @param message 用户消息
     * @param character 角色信息
     * @return AI回复内容
     */
    public Mono<String> chatWithCharacter(String message, AICharacter character) {
        return chatWithCharacter(message, character, null);
    }

    /**
     * 带历史记录的角色扮演聊天接口
     * @param message 用户消息
     * @param character 角色信息
     * @param chatHistory 聊天历史记录
     * @return AI回复内容
     */
    public Mono<String> chatWithCharacter(String message, AICharacter character, List<Map<String, String>> chatHistory) {
        String characterSystemPrompt = buildSystemPrompt(character);
        return chat(message, characterSystemPrompt, chatHistory);
    }

    /**
     * 构建角色系统提示词
     * @param character 角色信息
     * @return 系统提示词
     */
    private String buildSystemPrompt(AICharacter character) {
        StringBuilder prompt = new StringBuilder();
        prompt.append("你现在要扮演").append(character.getName()).append("。");

        if (character.getBackground() != null && !character.getBackground().isEmpty()) {
            prompt.append("\n背景设定：").append(character.getBackground());
        }

        if (character.getPersonality() != null && !character.getPersonality().isEmpty()) {
            prompt.append("\n性格特征：").append(character.getPersonality());
        }

        if (character.getSystemPrompt() != null && !character.getSystemPrompt().isEmpty()) {
            prompt.append("\n").append(character.getSystemPrompt());
        }

        prompt.append("\n请严格按照角色设定进行对话，保持角色的语言风格和行为特征。");

        return prompt.toString();
    }

    /**
     * 文生图接口
     * @param request 文生图请求
     * @return 文生图响应
     */
    public Mono<ImageGenerateResponse> generateImage(ImageGenerateRequest request) {
        Map<String, Object> requestBody = Map.of(
            "model", request.getModel(),
            "prompt", request.getPrompt(),
            "response_format", request.getResponseFormat(),
            "size", request.getSize(),
            "seed", request.getSeed() != null ? request.getSeed() : 12,
            "guidance_scale", request.getGuidanceScale(),
            "watermark", request.getWatermark()
        );

        log.info("开始发送豆包文生图API请求: URL={}, 模型={}, 提示词={}",
                doubaoProperties.getApi().getEndpoint() + "/images/generations",
                request.getModel(),
                request.getPrompt());

        return webClient.post()
                .uri("/images/generations")
                .header("Authorization", "Bearer " + doubaoProperties.getApi().getKey())
                .header("Content-Type", "application/json")
                .bodyValue(requestBody)
                .retrieve()
                .onStatus(status -> !status.is2xxSuccessful(),
                    response -> {
                        log.error("豆包文生图API返回非成功状态码: {}", response.statusCode());
                        return response.bodyToMono(String.class)
                            .doOnNext(errorBody -> log.error("错误响应体: {}", errorBody))
                            .map(errorBody -> {
                                return new RuntimeException("豆包文生图API错误: " + response.statusCode() + " - " + errorBody);
                            });
                    })
                .bodyToMono(String.class)
                .doOnNext(responseBody -> log.info("豆包文生图API原始响应: {}", responseBody))
                .timeout(Duration.ofSeconds(60)) // 文生图通常需要更长时间
                .map(this::parseImageResponse)
                .doOnNext(response -> log.info("豆包文生图API成功生成图像: {} 张", response.getData().size()))
                .doOnError(ex -> log.error("豆包文生图API调用过程中发生错误: ", ex))
                .onErrorMap(ex -> {
                    log.error("豆包文生图API调用失败，错误详情: {}", ex.getMessage(), ex);
                    return new RuntimeException("文生图服务暂时不可用，请稍后重试: " + ex.getMessage());
                });
    }

    /**
     * 解析文生图响应
     */
    private ImageGenerateResponse parseImageResponse(String responseJson) {
        try {
            log.info("解析豆包文生图API响应: {}", responseJson);
            JsonNode jsonNode = objectMapper.readTree(responseJson);

            // 检查是否有error
            if (jsonNode.has("error")) {
                String errorMessage = jsonNode.get("error").get("message").asText();
                log.error("豆包文生图API返回错误: {}", errorMessage);
                throw new RuntimeException("文生图服务错误: " + errorMessage);
            }

            ImageGenerateResponse response = new ImageGenerateResponse();

            // 设置基本信息
            response.setModel(jsonNode.get("model").asText());
            response.setCreated(jsonNode.get("created").asLong());

            // 解析图像数据
            List<ImageGenerateResponse.ImageData> imageDataList = new ArrayList<>();
            JsonNode dataArray = jsonNode.get("data");
            if (dataArray != null && dataArray.isArray()) {
                for (JsonNode imageNode : dataArray) {
                    ImageGenerateResponse.ImageData imageData = new ImageGenerateResponse.ImageData();
                    if (imageNode.has("url")) {
                        imageData.setUrl(imageNode.get("url").asText());
                    }
                    if (imageNode.has("b64_json")) {
                        imageData.setB64Json(imageNode.get("b64_json").asText());
                    }
                    imageDataList.add(imageData);
                }
            }
            response.setData(imageDataList);

            // 解析使用情况
            if (jsonNode.has("usage")) {
                JsonNode usageNode = jsonNode.get("usage");
                ImageGenerateResponse.Usage usage = new ImageGenerateResponse.Usage();
                usage.setGeneratedImages(usageNode.get("generated_images").asInt());
                if (usageNode.has("output_tokens")) {
                    usage.setOutputTokens(usageNode.get("output_tokens").asInt());
                }
                if (usageNode.has("total_tokens")) {
                    usage.setTotalTokens(usageNode.get("total_tokens").asInt());
                }
                response.setUsage(usage);
            }

            return response;

        } catch (Exception e) {
            log.error("解析文生图响应失败: {}", responseJson, e);
            throw new RuntimeException("文生图响应解析失败: " + e.getMessage());
        }
    }

    /**
     * 检查服务可用性
     */
    public Mono<Boolean> checkHealth() {
        return chat("你好")
                .map(response -> response != null && !response.trim().isEmpty())
                .onErrorReturn(false);
    }
}